/*
 * Programacao concorrente
 * Grupo-03a
 * Brenno Candido					7696500 
 * Jose Victor Uliana Martins		7656620
 * Maria Fernanda Garbim Avelino 	7277562
 */
	  
#include <stdio.h> /** scanf, printf **/
#include <stdlib.h> /** malloc **/
#include <math.h> /** pow, exp, sqrt **/

/*
 * Gerador de numeros aleatorios com distribuição normal
 * Esse tipo de numeros aleatorios deixa a solucao mais
 * acurado
 */
#include "rand_bm.c" /** boxmullerstate, initboxmullerstate, boxmullerrandom **/

double S, E, r, sigma, T;
int M;

/*
 * Funcao: Standard deviation (desvio padão)
 * Parametros:
 *	trials	-> dados amostrias
 *	mean 	-> media dos dados amostrias
 * Retorno:
 *	desvio padão referente aos dados amostrais
 */
double stddev(double trials[], double mean) {
	float sum = 0;
	int i;

	for(i=0; i<M; i++) {
		sum += pow(trials[i]-mean, 2);
	}

	return sqrt(sum/M);
}

/*
 * Funcao que realiza o algoritmo do black scholes utilizando
 * o metodo de monte carlo.
 * Ela sera responsavel por preencher o vertor trials e calcular
 * sua  media.
 */
double BlackScholes(double trials[]) {
	struct BoxMullerState state; // responsavel em gerar numeros aleatorios
	double t, aux, sum = 0;
	int i;
	
	initBoxMullerState(&state); // inicializa state para poder gerar numeros randomicos

	for(i=0; i<M; i++ ){
		t = S*exp( (r-0.5*sigma*sigma)*T + (sigma*sqrt(T)*boxMullerRandom(&state)));
		if(t-E > 0) {
			aux = (-1)*r*T;
			aux = exp(aux);
			trials[i] = aux*(t-E);
		}
		else {
			trials[i] = 0;
		}
		sum += trials[i]; // soma trials para ser tirado a media
	}

	return sum/M; // media
} 

int main() {
	double mean, std_dev, confwidth, confmin, confmax;

	// Variaveis de entrada
	scanf("%lf %lf %lf %lf %lf %d", &S, &E, &r, &sigma, &T, &M);
	printf("S\t%.4lf\n", S);
	printf("E\t%.4lf\n", E);
	printf("r\t%.4lf\n", r);
	printf("sigma\t%.4lf\n", sigma);
	printf("T\t%.4lf\n", T);
	printf("M\t%d\n", M);
	
	double trials[M];

	mean = BlackScholes(trials); // preenche trials e 
	std_dev = stddev(trials, mean);

	/** calculo do intervalo de confianca **/
	confwidth = 1.96*std_dev/sqrt(M);
	confmin = mean - confwidth;
	confmax = mean + confwidth;

	printf("Confidence interval: (%.4lf, %.4lf)\n", confmin, confmax);

	return 0;
}
